using AnimCollections;

namespace DA.AnimGraph {

    // 旧导出文件，也是现在的导出原型文件
    public class AnimGraphPublishAsset {
        public class Resource {
            public AUID uuid;
            public string url;
            public string url2;
        }

        public class Timeline {
            public AUID uuid;
            public TimelineEvent[] events;
        }

        public class TimelineEvent {
            public float time;
            public float endTime;
            public TimelineEventState state;
            public TimelineEventFlag flag;
            public TimelineEventParameter parameter;
        }

        public AUID fileUuid;
        public PublishGraph[] graphs;
        public Resource[] resources;
        public Timeline[] timelines;
    }

    public class PublishGraph {
        public AUID uuid;
        public AUID name;
        //public int rootNode;
        public PublishNode[] nodes;
    }

    public abstract unsafe class PublishNode {
        public AUID uuid;
        public PublishPerk[] perks;

        public abstract NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer);
        protected unsafe void ParsePerks(NodeLink* node, ref GraphBuffer buffer) {
            if (perks == null || perks.Length == 0) return;

            int perkCount = perks.Length;
            buffer.MallocNativeSimpleArray(out NativeSimpleArray<PerkLink> perkLinkArray, perkCount);

            for (int i = 0; i < perkCount; i++) {
                node->AddPerk(perks[i].Parse(perkLinkArray.GetPtrAt(i), ref buffer));
            }
        }

        protected void SetDebugInfo(NodeLink* node) {
            node->nodeUuid = uuid;
        }
    }

    public abstract unsafe class PublishPerk {
        public AUID uuid;

        public abstract PerkLink* Parse(PerkLink* perkLink, ref GraphBuffer buffer);
    }

    #region Nodes

    public class ClipPNode : PublishNode {
        public ClipNode.SetupData data;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            ClipNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class SimpleBlendPNode : PublishNode {
        public SimpleBlendNode.SetupData data;
        public int inputA;
        public int inputB;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            SimpleBlendNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            node->SetChildren(AGPParser.ParseNodes(pNodes, inputA, ref buffer), AGPParser.ParseNodes(pNodes, inputB, ref buffer));
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class BlendSpace2DPNode : PublishNode {
        public BlendSpace2DNode.SetupData data;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            BlendSpace2DNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class BlendSpace1DPNode : PublishNode {
        public BlendSpace1DNode.SetupData data;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            BlendSpace1DNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class StateMachinePNode : PublishNode {
        public StateMachineNode.SetupData data;
        public int[] inputChildren;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            StateMachineNode.New(out NodeLink* node, ref buffer, inputChildren.Length, data);
            SetDebugInfo(node);
            for (int i = 0; i < inputChildren.Length; i++) {
                node->SetChild(AGPParser.ParseNodes(pNodes, inputChildren[i], ref buffer), i);
            }
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class LayerBlendPNode : PublishNode {
        public LayerBlendNode.SetupData data;
        public int[] inputChildren;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            LayerBlendNode.New(out NodeLink* node, ref buffer, inputChildren.Length, data);
            SetDebugInfo(node);
            for (int i = 0; i < inputChildren.Length; i++) {
                node->SetChild(AGPParser.ParseNodes(pNodes, inputChildren[i], ref buffer), i);
            }
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class SelectPNode : PublishNode {
        public SelectNode.SetupData data;
        public int[] inputChildren;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            SelectNode.New(out NodeLink* node, ref buffer, inputChildren.Length, data);
            SetDebugInfo(node);
            for (int i = 0; i < inputChildren.Length; i++) {
                node->SetChild(AGPParser.ParseNodes(pNodes, inputChildren[i], ref buffer), i);
            }
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class RevolvePNode : PublishNode {
        public RevolveNode.SetupData data;
        public int[] inputChildren;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            RevolveNode.New(out NodeLink* node, ref buffer, inputChildren.Length, data);
            SetDebugInfo(node);
            for (int i = 0; i < inputChildren.Length; i++) {
                node->SetChild(AGPParser.ParseNodes(pNodes, inputChildren[i], ref buffer), i);
            }
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class AxisBlend1DPNode : PublishNode {
        public AxisBlend1DNode.SetupData data;
        public int[] inputChildren;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            AxisBlend1DNode.New(out NodeLink* node, ref buffer, inputChildren.Length, data);
            SetDebugInfo(node);
            for (int i = 0; i < inputChildren.Length; i++) {
                node->SetChild(AGPParser.ParseNodes(pNodes, inputChildren[i], ref buffer), i);
            }
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class SlotPNode : PublishNode {
        public SlotNode.SetupData data;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            SlotNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    public class SequencePNode : PublishNode {
        public SequenceNode.SetupData data;

        public override unsafe NodeLink* Parse(PublishNode[] pNodes, int index, ref GraphBuffer buffer) {
            SequenceNode.New(out NodeLink* node, ref buffer, data);
            SetDebugInfo(node);
            ParsePerks(node, ref buffer);
            return node;
        }
    }

    #endregion Nodes



    #region Perks

    public class TimelinePPerk : PublishPerk {
        public TimelinePerk.SetupData data;

        public override unsafe PerkLink* Parse(PerkLink* perkLink, ref GraphBuffer buffer) {
            // todo:将不包含事件的timeline过滤掉
            return TimelinePerk.NewWithExistingLink(perkLink, ref buffer, data);
        }
    }

    public class SyncGroupPPerk : PublishPerk {
        public SyncGroupPerk.SetupData data;

        public override unsafe PerkLink* Parse(PerkLink* perkLink, ref GraphBuffer buffer) {
            return SyncGroupPerk.NewWithExistingLink(perkLink, ref buffer, data);
        }
    }

    public class CurveSamplerPPerk : PublishPerk {
        public CurveSamplerPerk.SetupData data;

        public override unsafe PerkLink* Parse(PerkLink* perkLink, ref GraphBuffer buffer) {
            return CurveSamplerPerk.NewWithExistingLink(perkLink, ref buffer, data);
        }
    }

    #endregion Perks

}